package pay.portal;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.client.utils.URIBuilder;
import org.hibernate.internal.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import pay.base.BaseCtrl;
import pay.base.ResponseBase;
import pay.common.ConstantFYJZH;
import pay.common.ConstantOrderStatus;
import pay.common.ConstantsOrder;
import pay.common.ResultCode;
import pay.entity.SysUser;
import pay.entity.Trade;
import pay.portal.web.message.TradeFYReq;
import pay.portal.web.message.TradeReq;
import pay.portal.web.message.TradeRes;
import pay.service.IOrderHelper;
import pay.service.IPayBack;
import pay.service.IPreAuth;
import pay.service.ITrade;
import pay.service.ITransfer;
import pay.service.sys.ISysUser;
import pay.utils.BalanceUtils;
import pay.utils.DateUtil;
import pay.utils.FYApiUtil;
import pay.utils.RedisCilent;
import pay.utils.ReqToModelHelper;
import pay.utils.SecurityUtils;
import pay.utils.XmlUtils;

/**
 * @author 记录用户的交易数据
 */
@Controller
@RequestMapping(value = BaseCtrl.App + "/tradeCtrl")
public class TradeCtrl extends BaseCtrl {

	private Logger logger = LoggerFactory.getLogger(TradeCtrl.class);

	@Value("${fy.mchntCd}")
	private String mchnt_cd;

	@Autowired
	private ITrade tradeService;

	@Autowired
	private IOrderHelper orderHelperService;

	@Autowired
	private ISysUser userService;

	@Autowired
	// private IPreAuthHelper preAutherHelperService;
	/**
	 * 商户代码，从配置文件中读取
	 */
	@Value("${server.scheme}")
	private String serverScheme;

	@Value("${fy.goldAccount.pathBaseUrl}")
	private String pathBaseUrl; // 测试环境为/jzh 生产无。

	@Value("${fy.withdrawLogFilePath}")
	private String logFilePath;

	/**
	 * 金账户baseURl，从配置文件中读取
	 */
	@Value("${fy.goldAccount.baseUrl}")
	private String jzhBaseUrl;
	@Value("${producer.host}")
	private String host;
	@Value("${fy.goldAccount.logsBaseUrl}")
	private String logsBaseUrl;
	
	
	@Autowired
	private ITransfer transferService;
	
	@Autowired
	private IPreAuth preauthService;
	
	@Autowired
	private IPayBack paybackService;

	/**
	 * 查询金账户流水
	 * 
	 * @param req
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/list" , method = RequestMethod.POST)
	public ResponseBase<List<TradeRes>> getProList(@RequestBody TradeReq req) {
		ResponseBase<List<TradeRes>> resp = new ResponseBase<List<TradeRes>>();
		List<TradeRes> tradeResList = new ArrayList<TradeRes>();
		List<Trade> tradeList = new ArrayList<Trade>();

		Long userId = req.getUserId();

		Integer month = req.getMonth();

		Integer year = req.getYear();

		Integer curPage = req.getCurPage();

		Integer pageSize = req.getPageSize();

		Integer tradeType = req.getTradeType();
		if (userId == null || month == null || year == null || curPage == null
				|| pageSize == null) {
			resp.setMsg(ResultCode.PARAM_LACK.getMsg());
			resp.setResultCode(ResultCode.PARAM_LACK.getCode());
			return resp;
		}

		//限制销户用户-2.7.6
		SysUser user = userService.findById(userId);
		if(user == null  || user.getCloseAccount() ==1 ){
			resp.setResult(null);
			resp.setResultCode(ResultCode.USER_NOT_EXIST.getCode());
			resp.setMsg(ResultCode.USER_NOT_EXIST.getMsg());
			return resp;
		}

		logger.info(
				"查询账户流水 userId ={}, month={}, year ={},  curpage={}, pageSize={}",
				userId, month, year, curPage, pageSize);

		Long startTime = DateUtil.getFirstTimeOfMonth(year, month);

		Long endTime = DateUtil.getLastTimeOfMonth(year, month);

		try {
			tradeList = tradeService.getAll(userId, startTime, endTime,
					tradeType, curPage, pageSize);

			Integer totalNum = tradeService.getTotalNum(userId, startTime,
					endTime);

			if (tradeList != null && tradeList.size() > 0) {
				for (Trade trade : tradeList) {
					TradeRes tradeRes = new TradeRes();
					tradeRes.setCtsStr(DateUtil.longToLongDate(trade.getCts()));

					ReqToModelHelper.copyReqValueToModel(trade, tradeRes);
					tradeRes.setWithdrawStatus(trade.getWithdrawStatus());


					tradeResList.add(tradeRes);
				}
				resp.setSize(totalNum);
				resp.setResult(tradeResList);
				resp.setResultCode(ResultCode.SUCC.getCode());
			} else {
				resp.setSize(0);
				resp.setMsg(ResultCode.NO_DATA.getMsg());
				resp.setResultCode(ResultCode.NO_DATA.getCode());
			}
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
			resp.setMsg("操作异常，请重试");
			resp.setResultCode(ResultCode.FAILED.getCode());
		}

		return resp;
	}

	/**
	 * 提现通知接口
	 * 
	 * @param req
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/withdraw/notify" , produces = "application/json;charset=UTF8",  method = RequestMethod.POST)
	public ResponseBase<Boolean> withdrawNotify(TradeFYReq req) {
		logger.info("******进入富友提现回调函数！******");
		ResponseBase<Boolean> resp = new ResponseBase<Boolean>();
		/**
		 * 商户代码
		 */
		String mchnt_cd = req.getMchnt_cd();

		/**
		 * 流水号
		 */
		String mchnt_txn_ssn = req.getMchnt_txn_ssn();

		/**
		 * 交易日期
		 */
		String mchnt_txn_dt = req.getMchnt_txn_dt();

		/**
		 * 手机号码
		 */
		String mobile_no = req.getMobile_no();

		/**
		 * 充值金额
		 */
		String amt = req.getAmt();

		/**
		 * 备注
		 */
		String remark = req.getRemark();

		/**
		 * 签名数据
		 * 
		 * @return
		 */
		String signature = req.getSignature();

		logger.info("mchnt_txn_ssn = " + mchnt_txn_ssn);

		// 判断参数是否异常
		if (StringHelper.isEmpty(mchnt_cd)
				|| StringHelper.isEmpty(mchnt_txn_ssn)
				|| StringHelper.isEmpty(mchnt_txn_dt)
				|| StringHelper.isEmpty(mobile_no) || StringHelper.isEmpty(amt)
				|| StringHelper.isEmpty(remark)
				|| StringHelper.isEmpty(signature)) {
			resp.setMsg(ResultCode.PARAM_LACK.getMsg());
			resp.setResultCode(ResultCode.PARAM_LACK.getCode());
			return resp;
		}

		// 判断用户是否存在
		SysUser user = userService.getByPhoneNum(mobile_no);
		if (user == null) {
			logger.info("用户不存在， phone={}", mobile_no);
			resp.setMsg("该用户不存在");
			resp.setResult(false);
			resp.setResultCode(ResultCode.PARAM_LACK.getCode());
			return resp;
		}

		// 保存交易记录
		Trade trade = new Trade();
		trade.setAmt(new BigDecimal(BalanceUtils.getFYVal(amt)));
		trade.setCts(System.currentTimeMillis());
		trade.setMchnt_txn_ssn(mchnt_txn_ssn);
		trade.setFlowType(ConstantFYJZH.BALANCE_CUT);
		trade.setType(ConstantFYJZH.TRADE_TY_TX);
		trade.setUserId(user.getId());
		trade.setTradeDesc("提现");
		//tradeService.save(trade);

		resp.setResultCode(ResultCode.SUCC.getCode());
		resp.setMsg("提现回调成功");
		resp.setResult(true);
		return resp;
	}

	/**
	 * 充值通知接口
	 * 
	 * @param req
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/recharge/notify" , produces = "application/json;charset=UTF8" , method = RequestMethod.POST)
	public ResponseBase<Boolean> rechargeNotify(TradeFYReq req) {
		logger.info("******进入富友充值回调函数！******");
		ResponseBase<Boolean> resp = new ResponseBase<Boolean>();
		/**
		 * 商户代码
		 */
		String mchnt_cd = req.getMchnt_cd();

		/**
		 * 流水号
		 */
		String mchnt_txn_ssn = req.getMchnt_txn_ssn();

		/**
		 * 交易日期
		 */
		String mchnt_txn_dt = req.getMchnt_txn_dt();

		/**
		 * 手机号码
		 */
		String mobile_no = req.getMobile_no();

		/**
		 * 充值金额
		 */
		String amt = req.getAmt();

		/**
		 * 备注
		 */
		String remark = req.getRemark();

		/**
		 * 签名数据
		 * 
		 * @return
		 */
		String signature = req.getSignature();

		// 判断参数是否异常
		if (StringHelper.isEmpty(mchnt_cd)
				|| StringHelper.isEmpty(mchnt_txn_ssn)
				|| StringHelper.isEmpty(mchnt_txn_dt)
				|| StringHelper.isEmpty(mobile_no) || StringHelper.isEmpty(amt)
				|| StringHelper.isEmpty(remark)
				|| StringHelper.isEmpty(signature)) {
			resp.setMsg(ResultCode.PARAM_LACK.getMsg());
			resp.setResultCode(ResultCode.PARAM_LACK.getCode());
			return resp;
		}

		// 判断用户是否存在
		SysUser user = userService.getByPhoneNum(mobile_no);
		if (user == null) {
			logger.info("用户不存在， phone={}", mobile_no);
			resp.setMsg("该用户不存在");
			resp.setResultCode(ResultCode.PARAM_LACK.getCode());
			resp.setResult(false);
			return resp;
		}

		// 保存交易记录
		Trade trade = new Trade();
		trade.setAmt(new BigDecimal(BalanceUtils.getFYVal(amt)));
		trade.setCts(System.currentTimeMillis());
		trade.setMchnt_txn_ssn(mchnt_txn_ssn);
		trade.setFlowType(ConstantFYJZH.BALANCE_ADD);
		trade.setType(ConstantFYJZH.TRADE_TY_CZ);
		trade.setUserId(user.getId());
		trade.setTradeDesc("充值");
		//tradeService.save(trade);

		resp.setResultCode(ResultCode.SUCC.getCode());
		resp.setMsg("充值回调成功");
		resp.setResult(true);
		return resp;
	}

	/**
	 * 充值通知接口
	 * 
	 * @param req
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/trade/notify" , produces = "application/json;charset=UTF8" , method = RequestMethod.POST)
	public ResponseBase<Boolean> tradeNotify(TradeFYReq req) {
		logger.info("******进入预授权、划拨、冻结 回调函数！******");
		ResponseBase<Boolean> resp = new ResponseBase<Boolean>();




		String mchnt_cd = req.getMchnt_cd();
		String mchnt_txn_ssn = req.getMchnt_txn_ssn();
		String mchnt_txn_dt = req.getMchnt_txn_dt();
		String amt = req.getAmt();
		String suc_amt = req.getSuc_amt();
		String resp_code = req.getResp_code();
		String signature = req.getSignature();

		logger.info(
				"预授权、划拨、冻结的交易通知接口入参：mchnt_cd={},mchnt_txn_ssn={},mchnt_txn_dt={},amt={},suc_amt={},resp_code={},signature={}",
				mchnt_cd, mchnt_txn_ssn, mchnt_txn_dt, amt, suc_amt, resp_code,
				signature);
		
		String allUrl = amt + "|" + mchnt_cd + "|" + mchnt_txn_dt + "|"
				+ mchnt_txn_ssn + "|" + resp_code + "|" + suc_amt;
		logger.info("交易接口通知明文：allUrl={}", allUrl);
		
		// 如果交易已存在，则返回不进行下一步操作
		if (!RedisCilent.existsKey(mchnt_txn_ssn)) {
			logger.info("预授权、划拨、冻结的交易通知接口, 流水号已处理 mchnt_txn_ssn={}",  mchnt_txn_ssn);
			return null;
		}
				
		if (!SecurityUtils.verifySign(allUrl, signature)){
			logger.info("预授权、划拨、冻结的交易通知接口,参数校验失败 mchnt_txn_ssn={}",  mchnt_txn_ssn);
			resp.setResult(false);
			return resp;
		}

		
		// 判断参数是否异常
		if (StringHelper.isEmpty(mchnt_cd)
				|| StringHelper.isEmpty(mchnt_txn_ssn)
				|| StringHelper.isEmpty(mchnt_txn_dt)
				|| StringHelper.isEmpty(amt)
				|| StringHelper.isEmpty(suc_amt)
				|| StringHelper.isEmpty(resp_code)
				|| StringHelper.isEmpty(signature)) {
			logger.info("预授权、划拨、冻结的交易通知接口, 部分参数为空 mchnt_txn_ssn={}",  mchnt_txn_ssn);
			return null;
		}

//		if (mchnt_txn_ssn.endsWith(ConstantFYJZH.MSSN_YSQ)) {//预授权
//
//			String checkResult = queryTxn(mchnt_txn_ssn, "PW13");
//
//			String contractNo = getContractNo(checkResult);
//
//			logger.info("通过通知接口进行预授权--mchnt_txn_ssn={},  contractNo={}, checkResult",mchnt_txn_ssn, contractNo, checkResult);
//
//			// 预授权回调
//			//preauthService.updPreautResult(mchnt_txn_ssn, contractNo, true);
//
//		} else if (mchnt_txn_ssn.endsWith(ConstantFYJZH.MSSN_GM)) {//划拨
//			logger.info("通过通知接口进行划扣--mchnt_txn_ssn={}", mchnt_txn_ssn);
//			transferService.updTransferResult(mchnt_txn_ssn, true);
//
//		} else if (mchnt_txn_ssn.endsWith(ConstantFYJZH.MSSN_HK)) {// 回款
//			logger.info("通过通知接口进行回款划拨--mchnt_txn_ssn={}", mchnt_txn_ssn);
//			paybackService.updPaybackResult(mchnt_txn_ssn, true);
//		}
		
		return resp;
	}

	private Boolean updatePreAuthResult(String mchnt_txn_ssn,
			String contractNo, Boolean result) {

		Trade trade = tradeService.getFromRedis(mchnt_txn_ssn);
		if (trade != null) {
			trade.setResp_code("0000");
			trade.setContract_no(contractNo);
			// 添加到交易记录表中
			tradeService.save(trade);
			// 更改订单状态
			orderHelperService.updateOrderStatus(trade.getOrderId(),
					ConstantOrderStatus.PAY_STATUS_TRUE,
					ConstantOrderStatus.CONFIRM_STATUS_FALSE, contractNo,
					ConstantsOrder.ORDER_FYJZH_PRIX);
			// 从缓存中删除相关信息
			orderHelperService.deleteFromRedis(ConstantFYJZH.TRADE_RECORD,
					mchnt_txn_ssn);
		}

		return true;
	}

	 
	/**
	 * 根据交易类型和交易流水查询交易结果
	 * 
	 * @param txn_ssn
	 * @param busi_tp
	 * @return
	 */
	public String queryTxn(String txn_ssn, String busi_tp) {

		/**
		 * 流水号
		 */
		String mchnt_txn_ssn = txn_ssn;

		/**
		 * 起始时间
		 */
		String start_day = DateUtil.getNowDay();

		/**
		 * 截止时间
		 */
		String end_day = DateUtil.getNowDay();

		String cust_no = "";

		String txn_st = "1";

		String remark = "";

		String page_no = "1";

		String page_size = "10";

		String signature = "";

		String pathUrl = pathBaseUrl + "/queryTxn.action";
		URIBuilder builder = new URIBuilder().setScheme("https")
				.setHost(jzhBaseUrl).setPath(pathUrl);
		logger.info(builder.toString());
		Map<String, String> trimmedParams = new HashMap<>();

		String allUrl = busi_tp + "|" + cust_no + "|" + end_day + "|"
				+ mchnt_cd + "|" + mchnt_txn_ssn + "|" + page_no + "|"
				+ page_size + "|" + remark + "|" + start_day + "|" + txn_ssn
				+ "|" + txn_st;

		SecurityUtils.initPrivateKey();
		SecurityUtils.initPublicKey();

		signature = SecurityUtils.sign(allUrl);

		trimmedParams.put("mchnt_cd", mchnt_cd);
		trimmedParams.put("mchnt_txn_ssn", mchnt_txn_ssn);
		trimmedParams.put("busi_tp", busi_tp);
		trimmedParams.put("start_day", start_day);
		trimmedParams.put("end_day", end_day);
		trimmedParams.put("txn_ssn", txn_ssn);
		trimmedParams.put("cust_no", cust_no);
		trimmedParams.put("txn_st", txn_st);
		trimmedParams.put("remark", remark);
		trimmedParams.put("page_no", page_no);
		trimmedParams.put("page_size", page_size);
		trimmedParams.put("signature", signature);

		logger.info("查询交易记录的请求参数是 ：" + trimmedParams.toString());
		String openResult = FYApiUtil.doPost(builder, trimmedParams);
		logger.info("查询交易记录的结果是 ：" + openResult);
		return openResult;
	}

	public String getContractNo(String resultStr) {
		String contract_no = XmlUtils.getVal(resultStr, "contract_no");
		return contract_no;
	}


	/**
	 * 发送错误信息
	 * @param msgContent
     * @return
     */
	@ResponseBody
	@RequestMapping(value = "/trade/sendErrorMsg" , produces = "application/json;charset=UTF8" , method = RequestMethod.GET)
	public ResponseBase<Boolean> tradeNotify(@RequestParam String msgContent, @RequestParam String  emailMsgTitle, @RequestParam String emailMsgContent) {
		ResponseBase<Boolean> resp = new ResponseBase<>();

		try{
			tradeService.sendErrorMsg(msgContent, emailMsgTitle, emailMsgContent);
			resp.setResultCode(ResultCode.SUCC.getCode());
			resp.setResult(false);
			return  resp;
		} catch(Exception e){
			logger.error("发送错误信息错误 e={}", e);
			resp.setResultCode(ResultCode.FAILED.getCode());
			resp.setResult(false);
			return  resp;
		}



	}
}
